﻿using Microsoft.Office.Interop.Outlook;
using Microsoft.Office;
using System.Net;
using System.Text;
using System.Linq;
using System.IO;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace Citi.Helpers
{
    public class EmailHelper
    {
        // Summary:
        //     Spe  cifies the folder type for the current Outlook profile.
        [Serializable]
        public enum DefaultFolders
        {
            // Summary: The Deleted Items folder.
            DeletedItems = 3,
            // Summary: The Outbox folder.
            Outbox = 4,
            // Summary: The Sent Mail folder.
            SentMail = 5,
            // Summary: The Inbox folder.
            Inbox = 6,
            // Summary: The Calendar folder.
            Calendar = 9,
            // Summary: The Contacts folder.
            Contacts = 10,
            // Summary: The Journal folder.
            Journal = 11,
            // Summary: The Notes folder.
            Notes = 12,
            // Summary: The Tasks folder.
            Tasks = 13,
            // Summary: The Drafts folder.
            Drafts = 16,
            // Summary: The All Public Folders folder in the Exchange Public Folders store. Only available for an Exchange account.
            PublicFoldersAllPublicFolders = 18,
            // Summary: The Conflicts folder (subfolder of Sync Issues folder). Only available for an Exchange account.
            Conflicts = 19,
            // Summary: The Sync Issues folder. Only available for an Exchange account.
            SyncIssues = 20,
            // Summary: The Local Failures folder (subfolder of Sync Issues folder). Only available for an Exchange account.
            LocalFailures = 21,
            // Summary: The Server Failures folder (subfolder of Sync Issues folder). Only available for an Exchange account.
            ServerFailures = 22,
            // Summary: The Junk E-Mail folder.
            Junk = 23,
            // Summary: The RSS Feeds folder.
            RssFeeds = 25,
            // Summary: The To Do folder.
            ToDo = 28,
            // Summary:
            //     The top-level folder in the Managed Folders group. For more information on
            //     Managed Folders, see Help in Outlook 2007. Only available for an Exchange
            //     account.
            ManagedEmail = 29,
        }

        public class EmailData
        {
            public string From { get; set; }
            public string To { get; set; }
            public string Cc { get; set; }
            public string Bcc { get; set; }
            public string Subject { get; set; }
            public List<string> Attachments { get; set; }
            public string BodyMessage { get; set; }
            public string SentOnBehalfOfName { get; set; }
            public string Template { get; set; }
        }

        public class DownloadAttachmentData
        {
            public DefaultFolders DefaultFolder { get; set; }
            public string PartialSubject { get; set; }
            public string NonDefaultFolder { get; set; }
            public string PathToSave { get; set; }
            public DateTime? InitialDate { get; set; }
            public List<string> FileExtensions { get; set; }
            public string PartialFileName { get; set; }
            public OlDefaultFolders OlDefaultFolders { get { return (OlDefaultFolders)DefaultFolder; } }
        }

        private Application application;
        private _NameSpace nameSpace;
        private string Domain { get; set; }
        private string Proxy { get; set; }

        #region Constructors

        public EmailHelper(string user, string password)
        {
            ConnectOutlook(user, password);
        }

        private void ConnectOutlook(string user, string password)
        {
            application = new Application();
            nameSpace = application.GetNamespace("MAPI");
            nameSpace.Logon(user, password, false, true);
            nameSpace.GetDefaultFolder(OlDefaultFolders.olFolderSentMail);
        }

        public EmailHelper(string user, string password, string domain, string proxy)
        {
            Domain = domain;
            Proxy = proxy;
            ConnectOutlook(user, password);
        }

        public EmailHelper(string user, string password, string domain)
        {
            Domain = domain;
            ConnectOutlook(user, password);
        }

        public EmailHelper()
        {
            ConnectOutlook(string.Empty, string.Empty);
        }

        #endregion

        public void SendEmail(EmailData email)
        {
            var item = (_MailItem)application.CreateItem(OlItemType.olMailItem);
            item.Importance = OlImportance.olImportanceHigh;
            item.BodyFormat = OlBodyFormat.olFormatHTML;

            item.SentOnBehalfOfName = string.IsNullOrWhiteSpace(email.SentOnBehalfOfName) ? null : email.SentOnBehalfOfName;
            item.To = email.To;
            item.CC = email.Cc;
            item.BCC = email.Bcc;

            if (email.Attachments != null)
                email.Attachments.ForEach(x => item.Attachments.Add(x));

            item.Subject = email.Subject;
            item.HTMLBody = string.IsNullOrEmpty(email.Template)
                    ? email.BodyMessage
                    : GetEmailBody(email.Template);

            item.Send();
        }

        public void SendEmail(string from, string to, string cc, string bcc, string subject, string attachFiles, string bodyMessage)
        {
            SendEmail(new EmailData
                {
                    Attachments = new List<string> { attachFiles },
                    Bcc = bcc,
                    BodyMessage = bodyMessage,
                    Cc = cc,
                    From = from,
                    SentOnBehalfOfName = "*OT BR FPC Tasks <dl.ot.br.fpc.tasks@imcla.lac.nsroot.net>",
                    Subject = subject,
                    To = to,

                });
        }

        public static string GetEmailBody(string templatePath, string user = null, string password = null, string domain = null, string proxy = null)
        {
            using (var webClient = new WebClient())
            {
                //webClient.Headers.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
                if (user != null && password != null && domain != null)
                    webClient.Credentials = new NetworkCredential(user, password, domain);

                if (!string.IsNullOrEmpty(proxy))
                    webClient.Proxy = new WebProxy(proxy);

                try
                {
                   return webClient.DownloadString(templatePath);
                }
                catch
                {
                    webClient.Proxy = null;
                    return webClient.DownloadString(templatePath);
                }               
            }
        }

        public List<string> DownloadAttachment(DownloadAttachmentData downloadAttachmentData)
        {
            var attachments = new List<string>();
            var folder = string.IsNullOrEmpty(downloadAttachmentData.NonDefaultFolder)
                             ? nameSpace.GetDefaultFolder(downloadAttachmentData.OlDefaultFolders)
                             : GetNonDefaultFolder(downloadAttachmentData.NonDefaultFolder, nameSpace.Folders);

            if (folder == null) return null;

            foreach (var messageCom in folder.Items)
            {
                try
                {
                    if (!(messageCom is MailItem))
                        continue;

                    var message = (MailItem)messageCom;

                    if (message.SentOn.Date < downloadAttachmentData.InitialDate) continue;

                    if (message.Subject != null && message.Subject.ToUpper().Contains(downloadAttachmentData.PartialSubject.ToUpper())
                        && (downloadAttachmentData.InitialDate == null || message.SentOn.Date >= downloadAttachmentData.InitialDate))
                    {
                        if (message.Attachments.Count == 0) continue;

                        foreach (Attachment attachment in message.Attachments)
                        {
                            if (downloadAttachmentData.FileExtensions != null)
                            {
                                if (!downloadAttachmentData.FileExtensions.Contains(Path.GetExtension(attachment.FileName)))
                                    continue;
                            }

                            if (downloadAttachmentData.PartialFileName == null || attachment.FileName.Contains(downloadAttachmentData.PartialFileName))
                                SaveAttachment(downloadAttachmentData, attachment, attachments);
                        }
                    }
                }
                catch
                {
                    continue;           
                }
            }

            return attachments;
        }

        private static void SaveAttachment(DownloadAttachmentData downloadAttachmentData, Attachment attachment, List<string> attachments)
        {
            var filenamePath = Path.Combine(downloadAttachmentData.PathToSave, attachment.FileName);

            if (!Directory.Exists(downloadAttachmentData.PathToSave))
                Directory.CreateDirectory(downloadAttachmentData.PathToSave);

            attachments.Add(filenamePath);
            attachment.SaveAsFile(filenamePath);
        }

        private MAPIFolder GetNonDefaultFolder(string nonDefaultFolder, Folders folders)
        {
            foreach (Folder folder in folders)
            {
                if (folder.Name == nonDefaultFolder) return folder;

                if (folder.Folders == null) continue;

                var childFolder = GetNonDefaultFolder(nonDefaultFolder, folder.Folders);

                if (childFolder != null) return childFolder;
            }

            return null;
        }
    }
}
